local skynet = require "skynet"
require "skynet.manager"
local log = require "sky_log"
local config = require "robot_plat_config"
local handle_config = require "handle_config"
local cc = require "sky_call"
local queue = require "skynet.queue"
local Queue = queue()

local M = {
    robot_plat_config_raw = {},     
    robot_plat_config = {},
    robot_config = {},
    t_use_robots = {},
    ac_map = {},
    special_tarneeb_config = {},
}

--============================= Local Function =============================--
local function write_config_files(self)
    local now_date = os.date( "%Y%m%d",  os.time() )
    local f = io.open("./log/start_srv_config_"..now_date..".lua", "w+")
    if f then 
        local serpent = require "serpent"
        local start_conf = {}
        start_conf.robot_plat_config_raw = self.robot_plat_config_raw
        start_conf.robot_plat_config = self.robot_plat_config
        start_conf.robot_config = self.robot_config
        start_conf.ac_map = self.ac_map
        f:write("start_config=", serpent.block(start_conf))
        f:close()
    end
end

local function reset_one_robot_money(plat_id, robot_id, new_money, robot_money)
    local WMODE_TARNEEB_ROBOT_ADDMONEY = 1521
    local WMODE_TARNEEB_ROBOT_REDUCEMONEY = 1522

    local delta_money = tonumber(new_money) - tonumber(robot_money)
    local wmode
    if delta_money >= 0 then
        wmode = WMODE_TARNEEB_ROBOT_ADDMONEY
    else
        wmode = WMODE_TARNEEB_ROBOT_REDUCEMONEY
    end

    cc.call_memdb("tarneeb_reset_user_money", tonumber(plat_id), tonumber(robot_id), tonumber(delta_money), wmode)
end

--重新设置机器人携带金额
local function reset_total_robot_money(tarneeb_cfg, robot_config, plat_id)
    if not tarneeb_cfg
    or (type(tarneeb_cfg)~='table')
    or not robot_config
    or (type(robot_config)~='table')
    or not plat_id then
        log.error("reset_robot_money error!", " plat_id="..(plat_id or "nil"))
        return
    end

    local money_t = {}
    for _, v in pairs(tarneeb_cfg) do
        local min_carry = tonumber( (v.moneyRange or {}).min)
        if min_carry then
            table.insert(money_t, tonumber( (v.moneyRange or {}).min))
        end
    end

    if not money_t
    or not next(money_t) then
        log.error("reset_total_robot_money error! money_t=", money_t)
        return
    end

    local count = 0
    for _, v in pairs(robot_config) do
        local robot_money = cc.call_memdb("get_money", plat_id, tonumber(v.id))
     
        --随机不同桌的最低携带 1~6倍，若配置有写固定最小携带倍数，则读配置
        local index = math.random(1, #money_t)
        local new_money = money_t[index] * math.random(1, 6)

        local reset_robot_money_rate = skynet.getenv("reset_robot_money_rate")
        if reset_robot_money_rate then
            new_money =  money_t[index] * reset_robot_money_rate
        end
     
        reset_one_robot_money(plat_id, tonumber(v.id), new_money, robot_money)
        
        count = count + 1
        --local after_money = cc.call_memdb("get_money", plat_id, tonumber(v.id))
        --log.info("reset_total_robot_money: ", "robot_id="..tonumber(v.id)
        --    .." reset_total_robot_money before_money="..robot_money
        --    .." reset_total_robot_money after_money_money="..after_money )
    end

    log.warning("reset_total_robot_money totoal nums=", count)
end

--============================= MSG =============================--
function M:get_config_info(plat_id, svid, tid)
    local plat_info, svid_info, table_info

    plat_info = (self.robot_plat_config[tonumber(plat_id)] or {}).db_info
    if plat_info then
        svid_info = plat_info[tonumber(svid)]
    end
    if svid_info then
        table_info = (svid_info.tables or {})[tonumber(tid)]
    end

    if table_info then 
        return table_info
    elseif svid_info then 
        return svid_info
    end

    return plat_info
end

function M:get_server_config(plat_id, svid, tid)
    local plat_info, svid_info

    plat_info = (self.robot_plat_config[tonumber(plat_id)] or {}).db_info
    if plat_info then
        svid_info = plat_info[tonumber(svid)]
    end

    local ret = {}
    for k, v in pairs(svid_info or {}) do
        if k~='tables' then 
            ret[k] = svid_info[k]
        end
    end

    if tid
    and svid_info
    and svid_info.tables
    and svid_info.tables[tonumber(tid)] then 
        ret.tables = {[tonumber(tid)] = svid_info.tables[tonumber(tid)]}
    end

    return ret
end

function M:get_server_by_tid(plat_id, tid)
    local plat_info = (self.robot_plat_config[tonumber(plat_id)] or {}).db_info
    --log.debug("plat_info=", plat_info)

    local find_server = {}
    for _, server_info in pairs(plat_info or {}) do
        for _, table_info in pairs(server_info.tables or {}) do
            if tonumber(tid)==tonumber(table_info.tid) then 
                find_server = server_info
                break
            end
        end 
    end

    return find_server
end

function M:fill_web_info(platid, tid, followuid)
    --add_by_tid
    local svid
    if tid and tid~=0 then 
        local server_info = self:get_server_by_tid(tonumber(platid), tonumber(tid))
        if server_info then 
            svid = server_info.svid
        end

        return tonumber(svid), tonumber(tid)
    end
 
    --add_by_followuid
    if followuid and followuid~=0 then 
        local ret = cc.call_memcache("get_tid", "memcache_uid", platid, followuid)
        if ret then
            tid = ret
            local server_info = self:get_server_by_tid(tonumber(platid), tonumber(tid))
            if server_info then 
                svid = server_info.svid
            end
        else
            log.debug("fill_web_info error! ret=", ret)
        end

        return tonumber(svid), tonumber(tid)
    end
end

function M:get_buy_min(platid, svid, tid)
    local server_info = self:get_config_info(tonumber(platid), tonumber(svid))

    local tables_info = (server_info or {}).tables or {}
    local the_table_info = tables_info[tonumber(tid)] or {}
    local table_type = the_table_info.table_type
    local buy_min = the_table_info.buy_min

    return tonumber(buy_min)
end

function M:get_robot_id_tarneeb(platid, num, big_blind)
    if not big_blind
    or not self.special_tarneeb_config
    or not self.special_tarneeb_config[tonumber(platid)] then
        log.error("get_robot_id_tarneeb error!", self.special_tarneeb_config)
        return {}
    end

    local tarneeb_cfg = self.special_tarneeb_config[tonumber(platid)]
    local blind = tonumber(big_blind / 2)
    
    local min_carry, max_carry, fee_ratdio, min_cost
    for _, v in pairs(tarneeb_cfg) do
        if (blind)==tonumber(v.blind) then
            min_carry = tonumber( (v.moneyRange or {}).min)
            max_carry = tonumber( (v.moneyRange or {}).max)
            fee_ratdio = tonumber( v.feeRatio)
            min_cost = blind + (blind * (fee_ratdio or 0) )/100
            break
        end
    end
    if not min_carry
    or not max_carry
    or not fee_ratdio then
        log.error("get_robot_id_tarneeb error!", " min_carry="..(min_carry or "nil")
            .." max_carry="..(max_carry or "nil")
            .." fee_ratdio="..(fee_ratdio or "nil")
            .." min_cost="..(min_cost or "nil")
        )
        return {}
    end
    --没有最大限额时传的-1
    if max_carry==-1 then
        max_carry = 2^63 -1
    end

    --默认0
    local query_robots = self.robot_config[tonumber(platid)][0]

    local count = 0

    local ret_robots = {}
    for i=#query_robots, 1, -1 do
        count = count + 1
        local v = query_robots[i]
        if v and v.id then
            local money = cc.call_memdb("get_money", platid, tonumber(v.id))
            --log.info("money=", money.." robot_id="..(v.id))
            if money
            and (money>=min_carry)
            and (money>=min_cost)
            and (money<=max_carry) then 
                v.total_money = money
                if #query_robots > i then
                    table.insert(ret_robots, v)
                    self.t_use_robots[tonumber(v.id)] = v
                    table.remove(query_robots, i)
                end
                   
                if #ret_robots>=num then
                    break
                end
            end
        end
    end

    
    if count>60 then
        reset_total_robot_money(tarneeb_cfg, query_robots, platid)
    end

    --log.info("get_robot_id_tarneeb: ", " min_carry="..(min_carry or "nil")
    --    .." max_carry="..(max_carry or "nil")
    --    .." fee_ratdio="..(fee_ratdio or "nil")
    --    .." min_cost="..(min_cost or "nil")
    --)

    return ret_robots
end

function M:get_robot_id(platid, buy_min, num)
    if not self.robot_config
    or not self.robot_config[tonumber(platid)] 
    or not self.robot_config[tonumber(platid)][0] then
        log.error("get_robot_id error!")
        return {}
    end
    
    --默认0
    local query_robots =  self.robot_config[tonumber(platid)][0]

    local ret_robots = {}

    for i=#query_robots, 1, -1 do
        local v = query_robots[i]
        if v and v.id then
            --[[
            --debug: add test_uid
            for _, v1 in pairs(query_robots) do
                if tonumber(v1.id)==3148 then 
                    v = v1
                end
            end
            log.debug("get_robot_id add v=", v)
            --]]
            
            local money = cc.call_memdb("get_money", platid, tonumber(v.id))
            if money and (money>=buy_min) then 
    
                v.total_money = money
                if #query_robots > i then
                    table.insert(ret_robots, v)
                    self.t_use_robots[tonumber(v.id)] = v
                    table.remove(query_robots, i)
                end
                   
                if #ret_robots>=num then
                    break
                end
            end
        end
    end

    return ret_robots
end

function M:kick_robot(robot_id, plat_id)
    local query_robots = self.robot_config[tonumber(plat_id)][0]

    local robot = self.t_use_robots[tonumber(robot_id)]

    if robot then
        table.insert(query_robots, 1, robot)
    
        self.t_use_robots[tonumber(robot_id)] = nil
    end
end

--debug用
function M:get_infos(plat_id, robot_type)
    log.warning("self.t_use_robots=", self.t_use_robots)
    log.warning("unuse robot_nums=", #(self.robot_config[tonumber(plat_id)][tonumber(robot_type) or 0] or {}))
end

function M:reset_robot_money(plat_id)
    log.warning("reset_robot_money plat_id=", plat_id)
    local query_robots = self.robot_config[tonumber(plat_id)][0]
    local tarneeb_cfg = self.special_tarneeb_config[tonumber(plat_id)]

    reset_total_robot_money(tarneeb_cfg, query_robots, plat_id)
end

--============================= Init =============================--
function M:init()
    skynet.register(".config")

    --外网发布需指定平台ID
    local release_plat_id = tonumber(skynet.getenv("the_plat_id"))
    if release_plat_id then
        handle_config.init_plat_config(self, release_plat_id, "/data/gameserver/Poker/Config/Config.ini")
        return
    end

    --config&&dbs
    for plat_id, plat_config in pairs(config) do 
        handle_config.init_plat_config(self, plat_id, plat_config)
        --skynet.sleep(100)
    end

    --log.info("service_config self.robot_plat_config_raw=", self.robot_plat_config_raw)
    --log.info("service_config self.robot_plat_config=", self.robot_plat_config)
    --log.info("service_config self.robot_config=", self.robot_config)
    --log.info("service_config self.ac_map=", self.ac_map)
    --skynet.fork(write_config_files, self)
end

skynet.start(function ()
    skynet.dispatch("lua", function(session, address, cmd, ...)
        local f = M[cmd]
        if f then
            skynet.ret(skynet.pack( Queue(f, M, ...) ) )
        else
            error(string.format("Unknown command %s", tostring(cmd)))
        end
    end)

    M:init()
end)

return M